﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Synchronization.Files;
using System.IO;
using Natol.MSSyncFxProviders.AmazonS3;
using Microsoft.Synchronization;

namespace Natol.MSSyncFxProviders.AmazonS3.SampleConsoleApp
{
    class Program
    {
        static string[] commandList = { "SyncS32FS" };
        
        private static void ListCommands()
        {
            Console.WriteLine("Available commands:");
            commandList.ToList().ForEach(command =>
                    Console.WriteLine(String.Concat(" -", command))
                );
        }

        static void Main(string[] args)
        {

            Console.WriteLine("AmazonS3 For MS Sync Framework Sampler");
            ConsoleHelper.WriteLineBreak();

            //wait for user command
            bool keepLooking = true;

            while (keepLooking)
            {
                ConsoleHelper.WriteLineBreak();
                ListCommands();
                string usrInput = ConsoleHelper.AskForInfo("Enter a command (press ENTER to exit):").Trim();
                if (String.IsNullOrEmpty(usrInput))
                    keepLooking = false;

                else if (usrInput.ToLower().StartsWith("syncs32fs"))
                {
                    SyncS3ToFS();
                }
            }
        }

        static void SyncS3ToFS()
        {
            //collect source and destination parameters
            var s3loginData = new S3BucketLoginData
            {
                AWSAccessKey = ConsoleHelper.AskForInfo("AWS Access Key:"),
                AWSSecretKey = ConsoleHelper.AskForInfo("YOUR ACCESS KEY:"),
                BucketName = ConsoleHelper.AskForInfo("YOUR BUCKET NAME:")
            };
            string syncId = ConsoleHelper.AskForInfo("YOUR SYNC ID:");
            
            bool showDebugInfo = ConsoleHelper.AskYesNoQuestion("Show Detailed Debug information?");

            //ask user for a valid file system path
            DirectoryInfo destinationPath = ConsoleHelper.AskForValidFileSystemPath("Destination File System path", true);
            //destinationRootPaths.ToList().Where(!Directory.Exists).ForEach(Directory.CreateDirectory);

            //set up source S3 provider
            var s3Provider = new AWSS3SyncProvider(syncId, s3loginData);

            //set up destination FS provider
            FileSyncProvider fsProvider = new FileSyncProvider(destinationPath.FullName);

            //set up sync agent to download from s3 provider to FS provider
            SyncOrchestrator agent = new SyncOrchestrator
            {
                Direction = SyncDirectionOrder.Download,
                LocalProvider = fsProvider,
                RemoteProvider = s3Provider
            };

            //register events so that we can display status updates to the user


            if (showDebugInfo)
            {
                agent.SessionProgress += new EventHandler<SyncStagedProgressEventArgs>(agent_SessionProgress);
                agent.StateChanged += new EventHandler<SyncOrchestratorStateChangedEventArgs>(agent_StateChanged);

                fsProvider.DetectingChanges += new EventHandler<DetectingChangesEventArgs>(fsProvider_DetectingChanges);
            }

            s3Provider.ChangeDetectionCompleted += new EventHandler<Microsoft.Synchronization.SimpleProviders.ChangeDetectionCompletedEventArgs>(s3Provider_ChangeDetectionCompleted);            
            fsProvider.DetectedChanges += new EventHandler<DetectedChangesEventArgs>(fsProvider_DetectedChanges);


            //detect changes and report
            ConsoleHelper.AnyKey("Press ANY KEY to detect changes.",false);
            fsProvider.DetectChanges();

            //perform synchronise
            ConsoleHelper.AnyKey("Press ANY KEY to perform synchronisation.", false);
            SyncOperationStatistics syncStats = agent.Synchronize();
            WriteStats(syncStats);
        }

        static void fsProvider_DetectedChanges(object sender, DetectedChangesEventArgs e)
        {
            Console.WriteLine(
                "Found Changes: {0} directories, {1} files, {2} bytes",
                    e.TotalDirectoriesFound, 
                    e.TotalFilesFound, 
                    e.TotalFileSize
                );
        }

        static void fsProvider_DetectingChanges(object sender, DetectingChangesEventArgs e)
        {
            Console.WriteLine(
                String.Concat("Detecting changes in FS at ",
                    e.DirectoryPath)
                );
        }

        static void s3Provider_ChangeDetectionCompleted(object sender, Microsoft.Synchronization.SimpleProviders.ChangeDetectionCompletedEventArgs e)
        {
            Console.WriteLine("Finsihed detecting changes on S3");
        }

        static void agent_StateChanged(object sender, SyncOrchestratorStateChangedEventArgs e)
        {
            Console.WriteLine(
                "State changed from {0} to {1}",
                        e.OldState,
                        e.NewState
                    );
        }

        static void agent_SessionProgress(object sender, SyncStagedProgressEventArgs e)
        {
            Console.WriteLine(
                "Progress of {3} ({0}) - {1}/{2}",
                e.Stage.ToString(),
                e.CompletedWork,
                e.TotalWork,
                e.ReportingProvider.ToString()
               );
        }

        /// <summary>
        /// Display the statistics from the SyncOperationStatistics object that is returned by Synchronize()
        /// </summary>
        /// <param name="stats"></param>
        static void WriteStats(SyncOperationStatistics stats)
        {
            Console.WriteLine("Download Applied:\t {0}", stats.DownloadChangesApplied);
            Console.WriteLine("Download Failed:\t {0}", stats.DownloadChangesFailed);
            Console.WriteLine("Download Total:\t\t {0}", stats.DownloadChangesTotal);
            Console.WriteLine("Upload Total:\t\t {0}", stats.UploadChangesApplied);
            Console.WriteLine("Upload Total:\t\t {0}", stats.UploadChangesFailed);
            Console.WriteLine("Upload Total:\t\t {0}", stats.UploadChangesTotal);
        }
    }
}
